﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using System.Web.Security;
using PessMvc.Models;
using System.Web.Profile;
using PessMvc.Helpers;
using PessModel;
using System.Web.Script.Serialization;

namespace MvcApplication4.Controllers
{
    public class AccountController : Controller
    {
        PessModel.PESSEntities db = new PessModel.PESSEntities();

        [Authorize(Roles = "Admin")]
        public ActionResult RolesManagement()
        {
            return View(Roles.GetAllRoles());
        }

        [Authorize(Roles = "Admin")]
        public ActionResult EditUserRoles(string id)
        {
            IEnumerable<string> roles = Roles.GetAllRoles();
            MembershipUser user=Membership.GetUser(Guid.Parse(id), false);
            IEnumerable<string> inroles = Roles.GetRolesForUser(user.UserName);
            List<KeyValuePair<string, bool>> rolelist=new List<KeyValuePair<string,bool>>();
            foreach(string role in roles)
            {
                KeyValuePair<string, bool> chk;
                if(inroles.Count()!=0&&inroles.Contains(role))
                {
                    chk = new KeyValuePair<string, bool>(role, true);
                }
                else
                {
                    chk = new KeyValuePair<string, bool>(role, false);
                }
                rolelist.Add(chk);
            }
            ViewBag.RoleList=rolelist;
            return View(user);
        }

        [Authorize(Roles = "Admin")]
        [HttpPost]
        public ActionResult EditUserRoles(string id, List<RoleSelection> roles)
        {
            MembershipUser user = Membership.GetUser(Guid.Parse(id), false);
            Roles.RemoveUserFromRoles(user.UserName, Roles.GetRolesForUser(user.UserName));
            foreach (var r in roles)
            {
                if(r.IsSelected)
                {
                    Roles.AddUserToRole(user.UserName, r.RoleName);
                }
            }
            return RedirectToAction("UserManagement", "Account");
        }

        [Authorize(Roles = "Admin")]
        [HttpPost]
        public ActionResult DeleteUserConfirm(string userid)
        {
            
            Membership.DeleteUser(Membership.GetUser(Guid.Parse(userid), false).UserName);
            return RedirectToAction("UserManagement");
        }

        [Authorize(Roles = "Admin")]
        public ActionResult DeleteUser(string id)
        {
            ViewBag.Userid = id;
            Guid uid = Guid.Parse(id);
            ViewBag.Username = Membership.GetUser(uid).UserName;
            return View();
        }

        [Authorize(Roles="Admin")]
        public ActionResult UserManagement()
        {
            MembershipUserCollection users = Membership.GetAllUsers();
            List<UserModel> userlist = new List<UserModel>();
            foreach(MembershipUser user in users)
            {
                ProfileBase profile = ProfileBase.Create(user.UserName);
       
                UserModel um = new UserModel()
                {
                    UserName = user.UserName, 
                    FirstName = profile["FirstName"] == null ? "" : profile["FirstName"].ToString(),
                    LastName = profile["LastName"] == null ? "" : profile["LastName"].ToString(),
                    PhoneNumber = profile["PhoneNumber"] == null ? "" : profile["PhoneNumber"].ToString(),
                    SchoolName = profile["Organization"] == null ? "" : profile["Organization"].ToString(),
                    ProfessionalTitle = profile["ProfessionalTitle"] == null ? "" : profile["ProfessionalTitle"].ToString(),
                    Email=user.Email,
                   Roles=Roles.GetRolesForUser(user.UserName),
                    UserId = Membership.GetUser(user.UserName).ProviderUserKey.ToString()
                };
                userlist.Add(um);
            }
            return View(userlist);
        }


        [Authorize]
        public ActionResult EditAuthorInfo()
        {
            UserModel model = new UserModel() { UserName = Membership.GetUser().UserName };
            ProfileBase profile = ProfileBase.Create(model.UserName);
            model.FirstName = profile["FirstName"] == null ? "" : profile["FirstName"].ToString();
            model.LastName = profile["LastName"] == null ? "" : profile["LastName"].ToString();
            model.PhoneNumber = profile["PhoneNumber"] == null ? "" : profile["PhoneNumber"].ToString();
            model.SchoolName = profile["Organization"] == null ? "" : profile["Organization"].ToString();
            model.ZipCode = profile["ZipCode"] == null ? "" : profile["ZipCode"].ToString();
            model.StateProvince = profile["StateProvince"] == null ? "" : profile["StateProvince"].ToString();
            model.Country = profile["Country"] == null ? "" : profile["Country"].ToString();
            model.City = profile["City"] == null ? "" : profile["City"].ToString();
            model.Address1 = profile["Address1"] == null ? "" : profile["Address1"].ToString();
             model.Address2 = profile["Address2"]==null ? "" : profile["Address2"].ToString();
             model.ProfessionalTitle = profile["ProfessionalTitle"] == null ? "" : profile["ProfessionalTitle"].ToString();
             model.Email = Membership.GetUser().Email;
             model.Fax = profile["Fax"] == null ? "" : profile["Fax"].ToString();
            return View(model);
        }

        [Authorize]
        [HttpPost]
        public JsonResult EditAuthorInfo(UserModel model)
        {
            if (ModelState.IsValid)
            {
                MembershipUser user = Membership.GetUser(model.UserName);
                ProfileBase profile = ProfileBase.Create(model.UserName);
                profile["FirstName"] = model.FirstName;
                profile["LastName"] = model.LastName;
                profile["PhoneNumber"] = model.PhoneNumber;
                profile["Organization"] = model.SchoolName;
                profile["ZipCode"] = model.ZipCode;
                profile["StateProvince"] = model.StateProvince;
                profile["Country"] = model.Country;
                profile["City"] = model.City;
                profile["Address1"] = model.Address1;
                profile["Address2"] = model.Address2;
                profile["ProfessionalTitle"] = model.ProfessionalTitle;
                profile["Fax"] = model.Fax;
                profile.Save();
                if (User.IsInRole("Author"))
                    //return RedirectToAction("Index", "Author");
                    return Json(HttpContext.Request.Url.Scheme + "://" + HttpContext.Request.Url.Authority + Url.Action("Index", "Author"), JsonRequestBehavior.AllowGet);

                else
                    //return RedirectToAction("Settings", "Account");
                    return Json(HttpContext.Request.Url.Scheme + "://" + HttpContext.Request.Url.Authority + Url.Action("Settings", "Account"), JsonRequestBehavior.AllowGet);

            }

            //return View(model);
            return Json(HttpContext.Request.Url.Scheme + "://" + HttpContext.Request.Url.Authority + Url.Action("EditAuthorInfo"), JsonRequestBehavior.AllowGet);

        }

        public ActionResult CountyAdmins()
        {
            //string[] usersInRole = Roles.GetUsersInRole("CountyAdmin");
            //MembershipUserCollection users = new MembershipUserCollection();
            
            //foreach (string userName in usersInRole)
            //{
            //    users.Add(Membership.GetUser(userName));
            //}
            
            //return View(users);

            string[] usersInRole = Roles.GetUsersInRole("CountyAdmin");

            IList<CountyAdminModel> countyAdmins = new List<CountyAdminModel>();

            foreach (string userName in usersInRole)
            {
                MembershipUser user=Membership.GetUser(userName);
                ProfileBase profile=ProfileBase.Create(userName);
                string countyCode=profile["CountyCode"].ToString();
                CountyAdminModel countyAdmin = new CountyAdminModel() {  
                    CountyCode=countyCode, 
                    Email=user.Email, 
                    UserName=user.UserName, 
                    CountyName=getCountyName(countyCode)
                };
                countyAdmins.Add(countyAdmin);
            }

            return View(countyAdmins);

        }

        private string getCountyName(string countyCode)
        {
            return db.Counties.Find(countyCode).Name;
        }

        public ActionResult CountyAdminRegister()
        {
            PessModel.PESSEntities db = new PessModel.PESSEntities();
            ViewData["Counties"] = new SelectList(db.Counties,"Code","Name");
            return View();
        }

        public ActionResult EditCountyAdmin(string userName)
        {
            MembershipUser user = Membership.GetUser(userName);
            ProfileBase profile=ProfileBase.Create(userName);

            string countyCode=profile["CountyCode"].ToString();
            CountyAdminModel countyAdmin = new CountyAdminModel() { CountyCode = countyCode, CountyName = getCountyName(countyCode), Email=user.Email, UserName=userName };

            return View(countyAdmin);
        }

        [HttpPost]
        public ActionResult EditCountyAdmin(CountyAdminModel model)
        {
            if (ModelState["EMail"].Errors.Count==0)
            {
                MembershipUser user=Membership.GetUser(model.UserName);
                user.Email = model.Email;
                Membership.UpdateUser(user);
            }

            return RedirectToAction("CountyAdmins");
        }
        [HttpPost]
        public ActionResult DeleteCountyAdmin(string userName)
        {
            Membership.DeleteUser(userName);
            return RedirectToAction("CountyAdmins");
        }

        [HttpPost]
        public ActionResult CountyAdminRegister(CountyAdminModel model)
        {
            if (ModelState.IsValid)
            {
                // Attempt to register the user
                MembershipCreateStatus createStatus;
                Membership.CreateUser(model.UserName, model.Password, model.Email, null, null, true, null, out createStatus);
                if(createStatus==MembershipCreateStatus.Success)
                {
                    Roles.AddUserToRole(model.UserName, "CountyAdmin");
                    ProfileBase profile=ProfileBase.Create(model.UserName);
                    profile["CountyCode"]=model.CountyCode;
                    profile.Save();

                    return RedirectToAction("CountyAdmins","Account");
                }
                else
                {
                    ModelState.AddModelError("",createStatus.ToString());
                }
               
            }

            // If we got this far, something failed, redisplay form
            return View(model);            
        }
        //
        // GET: /Account/LogOn

        public ActionResult LogOn()
        {
            int caid = int.Parse(System.Configuration.ConfigurationManager.AppSettings["CurrentActivityID"]);
            Activity activity = db.Activities.Find(caid);
            ViewBag.ActivityStatus = activity.Status;
            Session["SignInType"] = "";
            return View();
        }

       public ActionResult RegLogOn()
        {
            int caid = int.Parse(System.Configuration.ConfigurationManager.AppSettings["CurrentActivityID"]);
            Activity activity = db.Activities.Find(caid);
            ViewBag.ActivityStatus = activity.Status;
            Session["SignInType"] = "Registration";
            return View();
        }

        //
        // POST: /Account/LogOn

        [HttpPost]
        public ActionResult LogOn(LogOnModel model, string returnUrl)
        {
            if (ModelState.IsValid)
            {
                int caid = int.Parse(System.Configuration.ConfigurationManager.AppSettings["CurrentActivityID"]);
                Activity activity = db.Activities.Find(caid);

                ViewBag.ActivityStatus = activity.Status;
                //if (activity != null)
                //{
                HttpContext.Session.Add("ActivityID", caid);
                //}

                

                model.UserName = model.UserName.Trim();
                string username=model.UserName;
                if(model.UserName.Contains('@') && model.UserName.Contains('.'))
                    username = Membership.GetUserNameByEmail(model.UserName);
                model.UserName = username;
                if (Membership.ValidateUser(model.UserName, model.Password))
                {
                    FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
                    MembershipUser user = Membership.GetUser(model.UserName);

                    if (activity.Status == 1 && !User.IsInRole("Admin"))
                    {
                        this.LogOff();
                    }
                    else if (activity.Status == 2 && !(User.IsInRole("Admin") || User.IsInRole("Chair") || User.IsInRole("Editor")))
                    {
                        this.LogOff();
                    }
                 

                    //This if guards the exception that expertjudge does not exist but user exists.
                    if (Roles.IsUserInRole(model.UserName, "ExpertJudge") && db.ExpertJudges.Find(model.UserName) == null)
                    {
                        this.LogOff();                     
                    }
                    if (!Utility.IsExpertJudgeInfoComplete(model.UserName))
                    {
                        //return RedirectToAction("ChangePassword");
                        return RedirectToAction("Edit", "ExpertJudge", new { serialNumber = model.UserName, returnUrl = returnUrl });
                    }
                    if(!Utility.IsExpertJudgePwdChanged(model.UserName))
                    {
                        return RedirectToAction("ChangePasswordandQA");
                    }
                    if (Roles.IsUserInRole(model.UserName, "ExpertJudge"))
                    {
                        return RedirectToAction("Index", "Archive", new {activityID=caid});
                    }
                    if (Roles.IsUserInRole(model.UserName, "Author"))
                    {
                        return RedirectToAction("Index","Author");
                    }
                    if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1 && returnUrl.StartsWith("/")
                        && !returnUrl.StartsWith("//") && !returnUrl.StartsWith("/\\"))
                    {
                        return Redirect(returnUrl);
                    }
                    else
                    {
                        return RedirectToAction("Index", "Activity");
                    }
                }
                else
                {
                    ModelState.AddModelError("", "Username or password error.");
                }
            }

            // If we got this far, something failed, redisplay form
            if (Session["SignInType"] != null && Session["SignInType"].ToString() == "Registration")
                return View("RegLogOn", model);
            else
                return View(model);
        }

        //
        // GET: /Account/LogOff

        public ActionResult LogOff()
        {
            FormsAuthentication.SignOut();
            HttpContext.Session["ActivityID"] = -1;
            if(Session["SignInType"]!=null&&Session["SignInType"].ToString()=="Registration")
                return RedirectToAction("RegLogOn", "Account");
            else
                return RedirectToAction("LogOn", "Account");
        }

        //
        // GET: /Account/Register

        public ActionResult Register()
        {
            return View();
        }

        //
        // POST: /Account/Register
        //This is only for author.
        [HttpPost]
        public ActionResult Register(RegisterModel model)
        {
            if (ModelState.IsValid)
            {
                // Attempt to register the user
                MembershipCreateStatus createStatus;
                model.UserName=model.Email;
                Membership.CreateUser(model.UserName, model.Password, model.Email,model.SecurityQuestion, model.SecurityAnswer, true, null, out createStatus);

                if (createStatus == MembershipCreateStatus.Success)
                {
                    Roles.AddUserToRole(model.UserName, "Author");
                    FormsAuthentication.SetAuthCookie(model.UserName, false /* createPersistentCookie */);
                    return RedirectToAction("Index", "Author");
                }
                else
                {
                    ModelState.AddModelError("", ErrorCodeToString(createStatus));
                }
            }

            // If we got this far, something failed, redisplay form
            return View(model);
        }

        //
        // GET: /Account/ChangePassword

        [Authorize]
        public ActionResult ChangePassword()
        {
            return View();
        }



        //
        // POST: /Account/ChangePassword

        [Authorize]
        [HttpPost]
        public ActionResult ChangePassword(ChangePasswordModel model)
        {
            if(model.OldPassword==model.NewPassword)
            {
                ModelState.AddModelError("", "New password and old password are same.");
            }
            if (ModelState.IsValid)
            {

                MembershipUser currentUser = Membership.GetUser(User.Identity.Name, true /* userIsOnline */);
                // ChangePassword will throw an exception rather
                // than return false in certain failure scenarios.
                bool changePasswordSucceeded;
                try
                {
                    changePasswordSucceeded = currentUser.ChangePassword(model.OldPassword, model.NewPassword);
                }
                catch (Exception)
                {
                    changePasswordSucceeded = false;
                }

                if (changePasswordSucceeded)
                {
                    currentUser.Comment = "";
                    Membership.UpdateUser(currentUser);
                    return RedirectToAction("ChangePasswordSuccess");
                }
                else
                {
                    ModelState.AddModelError("", "The current password is incorrect or the new password is invalid.");
                }
            }

            // If we got this far, something failed, redisplay form
            return View(model);
        }

        //
        // GET: /Account/ChangePassword
        // for first logon

        [Authorize]
        public ActionResult ChangePasswordandQA()
        {
            return View();
        }



        //
        // POST: /Account/ChangePassword1

        [Authorize]
        [HttpPost]
        public ActionResult ChangePasswordandQA(ChangePasswordQAModel model)
        {
            if (model.OldPassword == model.NewPassword)
            {
                ModelState.AddModelError("", "New password and old password are same.");
            }
            if (ModelState.IsValid)
            {

                // ChangePassword will throw an exception rather
                // than return false in certain failure scenarios.
                bool changePasswordSucceeded;
                try
                {
                    MembershipUser currentUser = Membership.GetUser(User.Identity.Name, true /* userIsOnline */);
                    changePasswordSucceeded = currentUser.ChangePassword(model.OldPassword, model.NewPassword);
                    currentUser.ChangePasswordQuestionAndAnswer(model.NewPassword, model.SecurityQeustion, model.Answer);
                }
                catch (Exception)
                {
                    changePasswordSucceeded = false;
                }

                if (changePasswordSucceeded)
                {
                    return RedirectToAction("ChangePasswordSuccess");
                }
                else
                {
                    ModelState.AddModelError("", "The current password is incorrect or the new password is invalid.");
                }
            }

            // If we got this far, something failed, redisplay form
            return View(model);
        }

        //
        // GET: /Account/ChangePasswordSuccess

        public ActionResult ChangePasswordSuccess()
        {
            return View();
        }

        #region Status Codes
        private static string ErrorCodeToString(MembershipCreateStatus createStatus)
        {
            // See http://go.microsoft.com/fwlink/?LinkID=177550 for
            // a full list of status codes.
            switch (createStatus)
            {
                case MembershipCreateStatus.DuplicateUserName:
                    return "User name already exists. Please enter a different user name.";

                case MembershipCreateStatus.DuplicateEmail:
                    return "A user name for that e-mail address already exists. Please enter a different e-mail address.";

                case MembershipCreateStatus.InvalidPassword:
                    return "The password provided is invalid. Please enter a valid password value.";

                case MembershipCreateStatus.InvalidEmail:
                    return "The e-mail address provided is invalid. Please check the value and try again.";

                case MembershipCreateStatus.InvalidAnswer:
                    return "The password retrieval answer provided is invalid. Please check the value and try again.";

                case MembershipCreateStatus.InvalidQuestion:
                    return "The password retrieval question provided is invalid. Please check the value and try again.";

                case MembershipCreateStatus.InvalidUserName:
                    return "The user name provided is invalid. Please check the value and try again.";

                case MembershipCreateStatus.ProviderError:
                    return "The authentication provider returned an error. Please verify your entry and try again. If the problem persists, please contact your system administrator.";

                case MembershipCreateStatus.UserRejected:
                    return "The user creation request has been canceled. Please verify your entry and try again. If the problem persists, please contact your system administrator.";

                default:
                    return "An unknown error occurred. Please verify your entry and try again. If the problem persists, please contact your system administrator.";
            }
        }
        #endregion

        //public ActionResult Search(int activityID, string userName,string roleName)
        //{
        //    var users=Membership.GetAllUsers().
        //}

        public ActionResult ResetPassword()
        {
            return View();
        }

        [HttpPost]
        public ActionResult GetQuestion(string email)
        {
            string username = Membership.GetUserNameByEmail(email);
            if(string.IsNullOrEmpty(username))
            {
                ViewBag.Message = email;
                return View(false);
            }
            else
            {
                ViewBag.Message = Membership.GetUser(username).PasswordQuestion;
                ViewBag.UserName = username;
                ViewBag.Email = email;
                return View(true);
            }
            
        }

        [HttpPost]
        public ActionResult ResetPassword(ResetPasswordModel model)
        {
            if (ModelState.IsValid)
            {
                try
                {
                    var user = Membership.GetUser(model.UserName);
                    string newpwd = user.ResetPassword(model.Answer);
                    user.Comment = "NCP";
                    Membership.UpdateUser(user);
                    string msg = Server.HtmlEncode(newpwd);
                    Utility.SendMail("Reset Password Successfully", "Here is your temporary password " + newpwd + "\r\n Please change your password when you log in.", model.Email);
                    return RedirectToAction("ResetPasswordSuccess", new { pwd = msg });
                }
                catch (Exception ex)
                {
                    ViewBag.Error = ex.Message;
                }
            }

            ViewBag.Message = Membership.GetUser(model.UserName).PasswordQuestion;
            ViewBag.UserName = model.UserName;
            ViewBag.Email = model.Email;
            return View("GetQuestion",true);
        }

        public ActionResult ResetPasswordSuccess(string pwd)
        {
            ViewBag.Msg = pwd;
            return View();
        }

        public ActionResult ReturnToUrl(string returnUrl)
        {
            if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1 && returnUrl.StartsWith("/")
                        && !returnUrl.StartsWith("//") && !returnUrl.StartsWith("/\\"))
            {
                return Redirect(returnUrl);
            }
            else
            {
                return RedirectToAction("Index", "Activity");
            }
        }

        //public ActionResult ChangePassword()
        //{
        //    return View();
        //}

        //[HttpPost]
        //public ActionResult ChangePassword(LocalPasswordModel model)
        //{
        //    if (model.OldPassword == model.NewPassword)
        //    {
        //        ModelState.AddModelError("NewPassword", "New password is the same as the old one.");
        //    }
        //    if (ModelState.IsValid)
        //    {
        //        // ChangePassword will throw an exception rather
        //        // than return false in certain failure scenarios.
        //        bool changePasswordSucceeded;
        //        try
        //        {
        //            MembershipUser currentUser = Membership.GetUser(User.Identity.Name, true /* userIsOnline */);
        //            changePasswordSucceeded = currentUser.ChangePassword(model.OldPassword, model.NewPassword);
        //        }
        //        catch (Exception)
        //        {
        //            changePasswordSucceeded = false;
        //        }

        //        if (changePasswordSucceeded)
        //        {
        //            return RedirectToAction("Logon");
        //        }
        //        else
        //        {
        //            ModelState.AddModelError("", "Wrong password.");
        //        }
        //    }

        //    // If we got this far, something failed, redisplay form
        //    return View(model);
        //}

        [Authorize]
        public ActionResult Settings()
        {
            int caid = int.Parse(System.Configuration.ConfigurationManager.AppSettings["CurrentActivityID"]);
            if (db.Activities.Find(caid) != null)
            {
                HttpContext.Session.Add("ActivityID", caid);
            }
            ViewBag.ActivityID = caid;
            return View();
        }

        [Authorize(Roles = "Admin")]
        public ActionResult CreateChair()
        {
            return View();
        }

        [Authorize(Roles = "Admin")]
        [HttpPost]
        public ActionResult CreateChair(RegisterModel model)
        {
            if (ModelState.IsValid)
            {
                // Attempt to register the user
                MembershipCreateStatus createStatus;
                model.UserName = model.Email;
                Membership.CreateUser(model.UserName, model.Password, model.Email, model.SecurityQuestion, model.SecurityAnswer, true, null, out createStatus);

                if (createStatus == MembershipCreateStatus.Success)
                {
                    Roles.AddUserToRole(model.UserName, "Chair");
                    //FormsAuthentication.SetAuthCookie(model.UserName, false /* createPersistentCookie */);
                    return RedirectToAction("UserManagement", "Account");
                }
                else
                {
                    ModelState.AddModelError("", ErrorCodeToString(createStatus));
                }
            }

            // If we got this far, something failed, redisplay form
            return View(model);
        }

        [Authorize(Roles = "Admin")]
        public ActionResult CreateEditor()
        {
            return View();
        }

        [Authorize(Roles = "Admin")]
        [HttpPost]
        public ActionResult CreateEditor(RegisterModel model)
        {
            if (ModelState.IsValid)
            {
                // Attempt to register the user
                MembershipCreateStatus createStatus;
                model.UserName = model.Email;
                Membership.CreateUser(model.UserName, model.Password, model.Email, model.SecurityQuestion, model.SecurityAnswer, true, null, out createStatus);

                if (createStatus == MembershipCreateStatus.Success)
                {
                    Roles.AddUserToRole(model.UserName, "Editor");
                    //FormsAuthentication.SetAuthCookie(model.UserName, false /* createPersistentCookie */);
                    return RedirectToAction("UserManagement", "Account");
                }
                else
                {
                    ModelState.AddModelError("", ErrorCodeToString(createStatus));
                }
            }

            // If we got this far, something failed, redisplay form
            return View(model);
        }
    }
}
